#include "Global.h"
#include <chrono>
#include "Gun.h"

namespace fs = std::filesystem;

GlobalConstant global_constant;
GlobalFunc global_func;

void GlobalFunc::delay(int timeout_ms)
{
	auto start = std::chrono::system_clock::now();
	while (true)
	{
		auto duration =
			std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start).count();
		if (duration >= timeout_ms)
		{
			break;
		}
	}
}

void GlobalConstant::set_gun_setting_select(const int gun_setting_select_key)
{
	this->open = 1;
	this->gun_setting_select_key = gun_setting_select_key;
	this->gun_setting_select_name = KeyGunMap[gun_setting_select_key];
	if (global_constant.qr_text)
	{
		global_func.unparkDraw();
	}
	LOG(INFO) << "Select Gun: " << KeyGunMap[gun_setting_select_key];
}

void GlobalConstant::set_open(const int open)
{
	this->open = open;
	LOG(INFO) << "Open: " << (open == 0 ? "OFF" : "ON");
}

void GlobalConstant::set_posture(const int posture)
{
	this->posture = posture;
	LOG(INFO) << "Posture: " << (posture == 0 ? "Z" : "D");
}

void GlobalConstant::set_fire_model(const int fire_model)
{
	this->fire_model = fire_model;
	LOG(INFO) << "Fire_model: " << (fire_model == 0 ? "single" : "full-automatic");
}

void GlobalConstant::set_is_complement(const int is_complement)
{
	this->is_complement = is_complement;
	LOG(INFO) << "Is_complement: " << (is_complement == 0 ? "REAL" : "FULL");
}

int GlobalConstant::loadSettings()
{
	std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
	long long timestamp = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
	if (timestamp - 3 > last_refresh_time)
	{
		LOG(INFO) << "Operate success!";
		last_refresh_time = timestamp;
		Json::Value guns_json = readJsonFile("guns.json");
		json2Guns(guns_json);
		return 1;
	}
	else
	{
		LOG(INFO) << "Operate too frequently!";
		return 0;
	}

}

void GlobalConstant::re_computeMovements()
{

	for (const auto& kv : global_constant.gunMap) {
		Gun gun = kv.second;
		gun.computeMovements();
		global_constant.gunMap[kv.first] = gun;
	}
}

void GlobalConstant::exited()
{
	LOG(INFO) << "exiting....";
	this->exit = true;
}

void GlobalFunc::park()
{
	std::unique_lock<std::mutex> lock(mtx);
	while (!ready) {
		cv.wait(lock);
	}
	// 重置条件，以便下次调用 park() 可以再次等待
	ready = false;
}

void GlobalFunc::unpark()
{
	std::lock_guard<std::mutex> lock(mtx);
	ready = true;
	cv.notify_one();
}

void GlobalFunc::parkDraw()
{
	std::unique_lock<std::mutex> lock(mtxDraw);
	while (!readyDraw) {
		cvDraw.wait(lock);
	}
	// 重置条件，以便下次调用 park() 可以再次等待
	readyDraw = false;
}


void GlobalFunc::unparkDraw()
{
	std::lock_guard<std::mutex> lock(mtxDraw);
	readyDraw = true;
	cvDraw.notify_one();
}